package com.bndg.blackjack

import android.util.Log


/**
 * @author r
 * @date 2024/10/12
 * @description 游戏控制器
 */

object BlackjackGame {
    // 监听器
    var listener: BlackjackListener? = null
    private val deck = Deck()
    private val playerHand = mutableListOf<Card>()
    private val dealerHand = mutableListOf<Card>()

    // 当前互动状态
    var gameState: GameState? = null

    /**
     * 开始游戏
     */
    fun startGame() {
        gameState?.let {
            // 清空手牌
            if(it.dealerChips < 50) {
                AppUtils.show("没有筹码了")
                return
            }
            it.playerCards?.clear()
            it.dealerCards?.clear()
            playerHand.clear()
            dealerHand.clear()
            // 重置游戏状态
            it.gameId = AppUtils.generateId()
            it.isInviteMsg = false
            it.isPlaying = true
            it.gameResult = GameResult.NORMAL
            it.gameAction = GameAction.INITIAL_DEAL
            it.currentTurn = Turn.PLAYER
            // 重新洗牌
            deck.resetCards()
            repeat(2) {
                playerHand.add(deck.drawCard() ?: return)
                dealerHand.add(deck.drawCard() ?: return)
            }
            val card = dealerHand[1]
            card.isFaceDown = true
            it.playerCards = playerHand
            it.dealerCards = dealerHand
            // 显示手牌 
            listener?.showHand(playerHand, dealerHand)
        }
    }

    /**
     * 检查是否结束
     */
    fun checkIsOver(): Boolean {
        gameState?.let {
            val gameResult = getGameResult(it.gameAction == GameAction.FINAL).first
            val isOver = when (gameResult) {
                GameResult.NORMAL -> {
                    false
                }
                else -> {
                    true
                }
            }
            AppUtils.log("checkIsOver: $isOver")
            if (isOver) {
                // 结束游戏 计算筹码
                if (gameResult != GameResult.TIE) {
                    if (gameResult == GameResult.PLAYER_WINS ||
                        gameResult == GameResult.DEALER_BUSTS ||
                        gameResult == GameResult.PLAYER_BLACKJACK
                    ) {
                        // 玩家胜 获得筹码*2
                        it.playerChips += it.currentChips * 2
                        it.dealerChips -= it.currentChips
                    } else {
                        // 庄家胜 获得筹码
                        it.dealerChips += it.currentChips
                    }
                } else {
                    // 平局 获得筹码
                    it.playerChips += it.currentChips
                }
                it.isPlaying = false
                it.currentChips = 0
                it.currentTurn = Turn.PLAYER
                it.gameResult = gameResult
                listener?.gameOver(gameResult)
            }
            return isOver
        }
        return false
    }

    /**
     * 玩家抽一张牌
     */
    fun playerHit() {
        gameState?.let {
            if (it.currentTurn != Turn.PLAYER) {
                AppUtils.show("等待庄家行动...")
                return
            }
            it.gameAction = GameAction.PLAYER_HIT
            playerHand.add(deck.drawCard() ?: return)
            dealerHand[1].isFaceDown = false
            it.dealerCards!![1].isFaceDown = false
            val card = playerHand[playerHand.size - 1]
//            it.playerCards?.add(card)
            AppUtils.log("playerHit: ${it.playerCards}")
            listener?.playerHitEnd(card)
        }

    }

    /**
     * 玩家停牌
     */
    fun playerStand() {
        gameState?.let {
            dealerHand[1].isFaceDown = false
            it.dealerCards!![1].isFaceDown = false
            it.gameAction = GameAction.PLAYER_STAND
            // 庄家回合
            it.currentTurn = Turn.DEALER
            listener?.playerStandEnd()
        }
    }

    /**
     * 庄家要牌
     */
    fun dealerHit() {
        gameState?.let {
            if (it.currentTurn != Turn.DEALER) {
                AppUtils.show("等待玩家行动...")
                return
            }
            dealerHand.add(deck.drawCard() ?: return)
            val card = dealerHand[dealerHand.size - 1]
            it.gameAction = GameAction.DEALER_HIT
//            it.dealerCards?.add(card)
            listener?.dealerHitEnd(card)
        }
    }

    /**
     * 计算牌面点数
     */
    fun calculateScore(hand: List<Card>): Int {
        if (hand.isEmpty()) return 0
        var score = hand.sumOf { it.value() }
        var aceCount = hand.count { it.rank == "A" }

        // 调整A的值
        while (score > 21 && aceCount > 0) {
            score -= 10
            aceCount--
        }
        return score
    }

    /**
     * 获取游戏结果
     * @param isPlayerStand 玩家是否停牌
     */
    fun getGameResult(
        isPlayerStand: Boolean = false,
    ): Pair<GameResult, Int?> {
        AppUtils.log("getGameResult: $isPlayerStand")
        gameState?.let {
            val playerScore = calculateScore(playerHand)
            val dealerScore = calculateScore(dealerHand)

            // 判断玩家的结果 BLACKJACK=A+10 J Q K
            val playerResult = when {
                playerScore > 21 -> GameResult.PLAYER_BUSTS
                playerScore == 21 && playerHand.size == 2 -> GameResult.PLAYER_BLACKJACK
                else -> GameResult.NORMAL // 玩家得分正常
            }

            // 判断庄家的结果
            val dealerResult = when {
                dealerScore > 21 -> GameResult.DEALER_BUSTS
                dealerScore == 21 && dealerHand.size == 2 -> GameResult.DEALER_BLACKJACK
                else -> GameResult.NORMAL // 庄家得分正常
            }
            // 如果玩家出现21点 并且当前是玩家的回合 那么到庄家回合 游戏仍然继续
            if (playerScore == 21 && it.currentTurn == Turn.PLAYER) {
                it.gameAction = GameAction.PLAYER_STAND
                it.currentTurn = Turn.DEALER
                listener?.playerStandEnd(true)
                return Pair(GameResult.NORMAL, null)
            }
            if (playerScore == 21 && dealerScore < 17) {
                if(playerResult != GameResult.PLAYER_BLACKJACK) {
                    // 庄家可以继续要牌
                    return Pair(GameResult.NORMAL, null)
                }
            }
            AppUtils.log("checkResult: $playerHand $dealerHand" )
            AppUtils.log("checkResult: $playerResult $playerScore  $dealerResult $dealerScore ")
            // 根据结果确定最终赢家
            return when {
                // 都爆牌 平局 游戏立即结束
                playerResult == GameResult.PLAYER_BUSTS && dealerResult == GameResult.DEALER_BUSTS ->
                    Pair(GameResult.TIE, null)
                // 玩家爆牌 庄家胜 游戏立即结束
                playerResult == GameResult.PLAYER_BUSTS -> Pair(
                    GameResult.PLAYER_BUSTS,
                    dealerScore
                )
                // 庄家爆牌 玩家胜 游戏立即结束
                dealerResult == GameResult.DEALER_BUSTS -> Pair(
                    GameResult.DEALER_BUSTS,
                    playerScore
                )
                // 都是黑杰克 游戏立即结束
                playerResult == GameResult.PLAYER_BLACKJACK && dealerResult == GameResult.DEALER_BLACKJACK ->
                    Pair(GameResult.TIE, null)
                // 玩家黑杰克 玩家胜 游戏立即结束
                playerResult == GameResult.PLAYER_BLACKJACK && dealerResult != GameResult.DEALER_BLACKJACK ->
                    Pair(GameResult.PLAYER_BLACKJACK, playerScore)
                // 庄家黑杰克 庄家胜 游戏立即结束
                dealerResult == GameResult.DEALER_BLACKJACK && playerResult != GameResult.PLAYER_BLACKJACK ->
                    Pair(GameResult.DEALER_BLACKJACK, dealerScore)
                // 出现普通的21点 回合切换到庄家
                playerScore == 21 || dealerScore == 21 -> Pair(
                    if (playerScore == dealerScore) GameResult.TIE else
                        if (playerScore == 21) GameResult.PLAYER_WINS else GameResult.DEALER_WINS,
                    null
                )
                // 玩家得分大 可以继续
                playerScore > dealerScore -> Pair(
                    if (isPlayerStand) GameResult.PLAYER_WINS else GameResult.NORMAL,
                    playerScore
                )
                // 庄家得分大 可以继续
                dealerScore > playerScore -> Pair(
                    if (isPlayerStand) GameResult.DEALER_WINS else GameResult.NORMAL,
                    dealerScore
                )

                else -> Pair(
                    if (isPlayerStand) GameResult.TIE else GameResult.NORMAL,
                    null
                ) // 平局  可以继续
            }
        }
        return Pair(GameResult.NORMAL, null)
    }

    /**
     * 获取花色
     */
    fun getSuit(suit: String): CharSequence {
        return when (suit) {
            "Hearts" -> "\u2665"
            "Diamonds" -> "\u2666"
            "Clubs" -> "\u2663"
            "Spades" -> "\u2660"
            else -> ""
        }
    }

    /**
     * 庄家行动
     */
    fun dealerAction() {
        gameState?.let {
            if (!it.isPlaying) return
//            if (checkIsOver()) return
            val dealerScore = calculateScore(dealerHand)
            // 庄家初始牌总点数为16或更低时：庄家必须继续抽牌。
            if (dealerScore < 17) {
                // 庄家总分小于硬 17，强制抽牌
                AppUtils.show("庄家点数小于17，自动抽牌")
                dealerHit()
            } else {
                // 游戏结束 计算
                it.gameAction = GameAction.FINAL
                listener?.needCheckOver()
            }
        }

    }

    /**
     * 退出
     */
    fun quit() {
        gameState = null
    }

    fun isPlayer(): Boolean {
        return MsgManager.myId == gameState?.playerId
    }

    fun getResultString(gameResult: GameResult): String {
        return when (gameResult) {
            GameResult.PLAYER_BUSTS -> return "玩家爆牌,庄家胜"
            GameResult.DEALER_BUSTS -> return "庄家爆牌,玩家胜"
            GameResult.PLAYER_BLACKJACK -> return "玩家黑杰克,玩家胜"
            GameResult.DEALER_BLACKJACK -> return "庄家黑杰克,庄家胜"
            GameResult.PLAYER_WINS -> return "玩家胜"
            GameResult.DEALER_WINS -> return "庄家胜"
            GameResult.TIE -> return "平局"
            else -> return ""
        }
    }

}